package com.deschen.security.core.authentication.mobile;

import org.springframework.context.support.MessageSourceAccessor;
import org.springframework.security.authentication.AuthenticationProvider;
import org.springframework.security.authentication.InternalAuthenticationServiceException;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.SpringSecurityMessageSource;
import org.springframework.security.core.authority.mapping.GrantedAuthoritiesMapper;
import org.springframework.security.core.authority.mapping.NullAuthoritiesMapper;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.util.Assert;

/**
 * @Author deschen
 * @Create 2019/8/23
 * @Description 手机认证的处理器
 * @Since 1.0.0
 */
public class MobileAuthenticationProvider implements AuthenticationProvider {

    protected MessageSourceAccessor messages = SpringSecurityMessageSource.getAccessor();

    private UserDetailsService userDetailsService;

    private GrantedAuthoritiesMapper authoritiesMapper = new NullAuthoritiesMapper();



    public void setUserDetailsService(UserDetailsService userDetailsService) {
        this.userDetailsService = userDetailsService;
    }

    @Override
    public Authentication authenticate(Authentication authentication) throws AuthenticationException {
        // 判断是否是手机认证
        Assert.isInstanceOf(MobileAuthenticationToken.class, authentication,
                messages.getMessage(
                        "MobileAuthenticationProvider.onlySupports",
                        "Only MobileAuthenticationToken is supported"));

        // 根据手机号获取用户信息
        MobileAuthenticationToken mobileAuthenticationToken = (MobileAuthenticationToken) authentication;
        UserDetails user = userDetailsService.loadUserByUsername((String) mobileAuthenticationToken.getPrincipal());
        if (user == null) {
            throw new InternalAuthenticationServiceException(
                    "UserDetailsService returned null, which is an interface contract violation");
        }

        // 封装已认证的手机信息
        MobileAuthenticationToken result = new MobileAuthenticationToken(
                user, authoritiesMapper.mapAuthorities(user.getAuthorities()));
        result.setDetails(authentication.getDetails());

        return result;
    }

    // 判断是否支持手机认证
    @Override
    public boolean supports(Class<?> authentication) {
        return (MobileAuthenticationToken.class
                .isAssignableFrom(authentication));
    }
}
